package com.znjc.iot.serial;

import com.znjc.iot.domain.IotSerial;
import com.znjc.iot.exception.NoSuchPort;
import com.znjc.iot.exception.NotASerialPort;
import com.znjc.iot.exception.PortInUse;
import com.znjc.iot.exception.SerialPortParameterFailure;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SerialTool {
    private final static Integer OPEN_OUT_TIME = 2000;

    /**
     * 私有化SerialTool类的构造方法，不允许其他类生成SerialTool对象
     */
    private SerialTool() {
    }


    /**
     * 打开串口
     *
     * @param serial 串口信息
     * @return 串口对象
     * @throws SerialPortParameterFailure 设置串口参数失败
     * @throws NotASerialPort             端口指向设备不是串口类型
     * @throws NoSuchPort                 没有该端口对应的串口设备
     * @throws PortInUse                  端口已被占用
     */
    public static final SerialPortUtil openPort(IotSerial serial)
            throws SerialPortParameterFailure, NotASerialPort, NoSuchPort,
            PortInUse {
        try {
            // 修正为跨平台写法（自动检测驱动）
            CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(serial.getSerialCode());  // Linux串口设备路径
            // 判断端口类型是否为串口
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                if (portId.getName().equals(serial.getSerialCode())) {
                    //打开串口
                    SerialPort serialPort = (SerialPort) portId.open(portId.getName(), OPEN_OUT_TIME);
                    SerialPortUtil serialPortVo = new SerialPortUtil(serialPort);
                    serialPortVo.setName(serial.getSerialCode());
                    serialPortVo.setIotSerial(serial);
                    // 设置串口的一些读写参数
                    try {
                        log.info("设置一下串口的波特率等参数");
                        // 设置一下串口的波特率等参数
                        serialPort.setSerialPortParams(serial.getBaudRate(),
                                serial.getDataBit(), serial.getStopBit(),
                                serial.getCheckoutBit());
                        log.info("设置一下串口的波特率等参数完成");
                    } catch (UnsupportedCommOperationException e) {
                        e.printStackTrace();
                    }
                    log.info(serial.getSerialCode() + "打开成功");
                    return serialPortVo;
                }
            } else {
                // 不是串口
                log.error("这不是一个串口");
                throw new NotASerialPort();
            }
        } catch (PortInUseException e2) {
            log.error("打开串口失败,端口已被占用：{}", e2);
            throw new PortInUse();
        } catch (NoSuchPortException e) {
            e.printStackTrace();
        }
        return null;
    }
}
